import java.util.PriorityQueue;
//通过这个类来描述一个任务
class MyTimerTask implements Comparable<MyTimerTask>{
    //在什么时间点来执行这个任务
    //此时我们约定这个time就是一个毫秒级别的时间戳
    private long time;
    //实际任务要执行的代码
    private Runnable runnable;
    public MyTimerTask(Runnable runnable,long delay){
        this.runnable = runnable;
        //计算一下要执行这个任务的绝对时间
        this.time = System.currentTimeMillis()+delay;
    }

    public long getTime() {
        return time;
    }

    public void run(){
        runnable.run();
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time-o.time);
    }

}
class MyTimer{
    //通过这个类来表示一个定时器
    //负责扫描任务队列，并且执行任务的线程
    private Thread t = null;
    //搞个锁对象
    private Object locker = new Object();
    //任务队列
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue();
    public void schedule(Runnable runnable,long delay){
        synchronized (locker){
            MyTimerTask task = new MyTimerTask(runnable,delay);
            queue.offer(task);
            //添加新的元素之后，就可以唤醒扫描线程的wait了
            locker.notify();
        }
    }
    //构造方法，创建扫描线程，让扫描线程来完成判定和执行
    public  MyTimer(){
        t = new Thread(()->{
            //扫描线程要循环反复的扫描队首元素，判定队首元素是否时间到了
            //如果时间没到就啥都不干，如果时间到了，就执行这个任务并把这个任务从队列中删除掉
          synchronized (locker){
              while (true){
                  try {
                      while (queue.isEmpty()){
                          locker.wait();
                      }
                      MyTimerTask task = queue.peek();
                      //获取当前时间
                      long curTime = System.currentTimeMillis();
                      if (curTime >= task.getTime()){
                          //当前时间已经达到任务时间，就可以执行任务
                          queue.poll();
                          task.run();
                      }else {
                          //当前时间还没到，暂时先不执行
                          locker.wait(task.getTime() - curTime);
                      }
                  }catch (InterruptedException e){
                      e.printStackTrace();
                  }
              }//解锁了
          }
        });
        t.start();
    }
}
public class demo {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);
        System.out.println("hello main");
    }
}

